package com.ihunanren.common.spider;

import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.ihunanren.common.CollectionUtils;

/**
 * @author kalman03
 */
public class WebPage {
	private final static Logger log = Logger.getLogger("WebSpider");

	private final Parser parser;
	/**当前页面的爬取深度*/
	private final int deep;
	private final String curUrl;
	
	private final URLConnection connection;

	private Set<String> emailLinkList = new HashSet<String>();
	private Set<String> httpLinkList = new HashSet<String>();
	private Set<String> httpsLinkList = new HashSet<String>();
	private Set<String> allLinkList = new HashSet<String>();
	private Set<String> javascriptLinkList = new HashSet<String>();
	private Set<String> ftpLinkList = new HashSet<String>();
	private Set<String> ircLinkList = new HashSet<String>();

	public WebPage(String link,int deep) throws Exception {
		this.deep = deep;
		this.connection = getConnection(link);
		this.curUrl = getCruLink();
		this.parser = new Parser(connection);
		if (this.parser == null)
			return;
		initAllLinks();
	}
	
	private URLConnection getConnection(String link) throws Exception {
		URL url = new URL(link);
		HttpURLConnection con = null;
		con = (HttpURLConnection) url.openConnection();
		con.setAllowUserInteraction(false);
		con.setConnectTimeout(2000);
		con.setReadTimeout(2000);
		con.setRequestMethod("GET");
		if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
			return con;
		}
		return con;
	}

	private String getCruLink(){
		try {
			return UrlHelper.formatLink(connection.getURL());
		} catch (MalformedURLException e) {
			log.log(Level.WARNING, "catch a exception.", e);
			e.printStackTrace();
		}
		return null;
	}

	private void initAllLinks() throws ParserException {
		// 通过过滤器过滤出<A>标签
		NodeList nodeList = null;
		nodeList = parser.extractAllNodesThatMatch(new NodeFilter() {
			private static final long serialVersionUID = 1L;
			// 实现该方法,用以过滤标签
			public boolean accept(Node node) {
				if (node instanceof LinkTag) // <A>标记
					return true;
				return false;
			}
		});

		if (nodeList == null)
			return;
		for (int i = 0; i < nodeList.size(); i++) {
			LinkTag tag = (LinkTag) nodeList.elementAt(i);
			String link = tag.extractLink();
			if (Strings.isNullOrEmpty(link))
				continue;
			allLinkList.add(link);
			if (tag.isHTTPLink()) {
				httpLinkList.add(link);
			} else if (tag.isJavascriptLink()) {
				javascriptLinkList.add(link);
			} else if (tag.isMailLink()) {
				emailLinkList.add(link);
			} else if (tag.isHTTPSLink()) {
				httpsLinkList.add(link);
			} else if (tag.isFTPLink()) {
				ftpLinkList.add(link);
			} else if (tag.isIRCLink()) {
				ircLinkList.add(link);
			}
		}
	}

	public Set<String> getMatchedLinkList(String ... regex) {
		if (!hasHttpLinks())
			return null;
		if (regex== null || regex.length<=0)
			return httpLinkList;
		Set<String> list = Sets.newHashSet();
		for (String link : httpLinkList) {
			for(String reg : regex){
				if (link.matches(reg)){
					list.add(link);
					break;
				}
			}
		}
		return list;
	}

	public boolean hasHttpLinks() {
		return CollectionUtils.isNotEmpty(httpLinkList);
	}

	public Set<String> getEmailLinkList() {
		return emailLinkList;
	}

	public Set<String> getHttpLinkList() {
		return httpLinkList;
	}

	public Set<String> getHttpsLinkList() {
		return httpsLinkList;
	}

	public Set<String> getAllLinkList() {
		return allLinkList;
	}

	public Set<String> getJavascriptLinkList() {
		return javascriptLinkList;
	}

	public Set<String> getFtpLinkList() {
		return ftpLinkList;
	}

	public Set<String> getIrcLinkList() {
		return ircLinkList;
	}
	
	public int getDeep() {
		return deep;
	}

	public String getCurUrl() {
		return curUrl;
	}
}
